<?php
/**
 * 级联选择器
 * 应用场景1：保持所有选择器
 * <pre>
 *  # district：一个四级的地址联动
 *  $ls=$form->linkage('district');
 *  # dropDownList(mode,attribute,layer);
 *  echo $ls->dropDownList($model, 'province', 1);
 *  echo $ls->dropDownList($model, 'city', 2);
 *  echo $ls->dropDownList($model, 'area', 3);
 *  echo $ls->dropDownList($model, 'community', 4);
 * </pre>
 * 应用场景2：保持个别选择器
 * <pre>
 *  ......
 *  # 设置htmlOptions的keep选项即可，没有值的情况下或初始状态不显示该选择器
 *  echo $ls->dropDownList($model, 'area', 3, array('keep'=>false));
 *  echo $ls->dropDownList($model, 'community', 4, array('keep'=>false));
 *  ......
 * </pre>
 * 应用场景3：无限选择（endless）模式，一般用于单个值的选择，例如商品的分类
 * <pre>
 *  # district：一个四级的地址联动
 *  $ls=$form->linkage('product_cate');
 *  # 不用设置第三个参数，或者将其设置为null即可
 *  echo $ls->dropDownList($model, 'cate_id');
 * </pre>
 * @author yangdongqi <yangdongqi@hayzone.com>
 * @package lib.components.linkage
 */
class CLinkageSelector extends CComponent {
	
	/**
	 * ActiveForm
	 * @var CActiveForm
	 */
	public $form;
	/**
	 * 配置名称
	 * @var string
	 */
	public $name;
	
	/**
	 * 分组名称
	 * @var string
	 */
	protected $_group;
	
	/**
	 * 使用过的value缓冲值
	 * <pre>
	 * array(
	 *  'layer1'=>'value1',
	 *  'layer2'=>'value2',
	 *  ......
	 *  'layerN'=>'valueN',
	 * )
	 * </pre>
	 * Enter description here ...
	 * @var unknown_type
	 */
	protected $_values = array();
	
	/**
	 * 注册JS文件
	 */
	public function __construct() {
		self::registerScriptFile();
	}
	
	/**
	 * 获取Group的值
	 * @return string
	 */
	public function getGroup() {
		if(!$this->_group) {
			static $count = 0;
			$this->_group = 'ls_'.(++$count);
		}
		return $this->_group;
	}
	
	/**
	 * 输出dropDownList
	 * @param CModel $model
	 * @param string $attribute
	 * @param int $layer
	 * @param array $htmlOptions
	 * 特殊的选项：<br/>
	 * keep: 保持显示<br/>
	 * endless: 用于单值的级联选择
	 * @return string
	 */
	public function dropDownList($model, $attribute, $layer = null, $htmlOptions=array()) {
		$parent = '';
		$group = $this->getGroup();
		$name = $this->name;
		$ls = Yii::app()->linkageSelector;
		$url = Yii::app()->createUrl($ls->getRoute());
		
		$data = array();
		
		$value = CHtml::value($model, $attribute);
		if($layer) {
			$this->_values[$layer] = $value;
			$parent = isset($this->_values[$layer-1]) ? $this->_values[$layer-1] : null;
		} else {
			$layer = 1;
			$htmlOptions['endless'] = true;
		}
		
		$data = $ls->loadData($this->name, $layer, $parent);
		
		$htmlOptions = $this->resolveHtmlOptions($htmlOptions, $layer);
		$endless = (int)(isset($htmlOptions['endless']) ? $htmlOptions['endless'] : false);
		$keep = (int)(isset($htmlOptions['keep']) ? $htmlOptions['keep'] : !$endless);
		
		unset($htmlOptions['endless'], $htmlOptions['keep']);

		$hiddenFiled = $endless ? $this->form->hiddenField($model, $attribute) : '';
		
		# endless的填充
		if($endless && $value) {
			$nodePath = $ls->getNodePath($name, $value);
			$html = '';
			$nextValue = '';
			$layer = 1;
			list($rModel, $rAttr, $rHtmlOptions) = $this->form->resolveArgs($model, $attribute, $htmlOptions);
			$nodePath[] = '';
			foreach($nodePath as $k=>$v) {
				$value = $nextValue ? $nextValue : null;
				
				$data = $ls->loadData($name, $layer, $value);
				$htmlOptions['layer'] = $layer;
				
				$this->registerNodeScript($group, $layer, array(
					'name' => $name,
					'url' => $url,
					'keep' => $keep,
					'endless' => $endless
				));
				
				if($v) $rModel->$rAttr = $k;
				if($data['itemCount']>0) {
					$html = $html . ' ' . $this->form->dropDownList(
						$model, $attribute, $data['data'], $htmlOptions
					);
				}
				
				$nextValue = $k;
				++$layer;
			}
			return $html.$hiddenFiled;
		}
		
		if(!$keep && $data['itemCount'] == 0) {
			if(isset($htmlOptions['style'])) {
				$htmlOptions['style'] .= ';display:none';
			} else {
				$htmlOptions['style'] = 'display:none';
			}
		}
		
		$this->registerNodeScript($group, $layer, array(
			'name' => $name,
			'url' => $url,
			'keep' => $keep,
			'endless' => $endless
		));
		
		return $this->form->dropDownList($model, $attribute, $data['data'], $htmlOptions).$hiddenFiled;
		
	}
	
	/**
	 * 注册节点的JS代码
	 * @param string $group
	 * @param int $layer
	 * @param array $params
	 * @return void
	 */
	public function registerNodeScript($group, $layer, $params = array()) {
		$script = <<<EOD
$('.linkage-selector[group="{$group}"][layer="{$layer}"]').linkageselector("{$params['name']}", "{$params['url']}", {$params['keep']}, {$params['endless']});	
EOD;
		if(Yii::app()->request->isAjaxRequest) {
			echo "<script>
			$().ready(function() {{$script}});
			</script>";
		} else {
			Yii::app()->clientScript->registerScript(
				$group.$layer, $script, CClientScript::POS_END
			);
		}
		
		
	}
	
	/**
	 * 解决htmlOptions
	 * @param array $htmlOptions
	 * @param int $layer
	 * @return array
	 */
	protected function resolveHtmlOptions($htmlOptions, $layer) {
		if(isset($htmlOptions['class'])) {
			$htmlOptions['class'] .= ' linkage-selector';
		} else {
			$htmlOptions['class'] = 'linkage-selector';
		}
		
		$htmlOptions = array_merge($htmlOptions, array(
			'layer' => $layer,
			'group' => $this->getGroup(),
		));
		return $htmlOptions;
	}
	
	/**
	 * 注册JS脚本文件
	 * @return void
	 */
	public static function registerScriptFile() {
		$cs = Yii::app()->clientScript;
		$am = Yii::app()->assetManager;
		$url = $am->publish(dirname(__FILE__).'/assets/jquery.linkageselector.js');
		if(Yii::app()->request->isAjaxRequest) {
			echo "<script src='{$url}'></script>";
		} else {
			$cs->registerScriptFile($url);
		}
	}
	
	

}

?>